package com.ts.api.module.test.service.impl;

import com.gitee.apanlh.util.algorithm.encrypt.symmetric.AES;
import com.gitee.apanlh.util.dataformat.JsonUtils;
import com.gitee.apanlh.util.date.DateUtils;
import com.gitee.apanlh.util.encode.HexUtils;
import com.gitee.apanlh.util.log.Log;
import com.gitee.apanlh.util.reflection.ClassConvertUtils;
import com.gitee.apanlh.util.reflection.CopyUtils;
import com.gitee.apanlh.util.valid.Assert;
import com.gitee.apanlh.util.valid.ValidParam;
import com.gitee.apanlh.web.model.vo.RequestVO;
import com.ts.api.common.constant.productflow.ProductApplyFlowSrcTypeEnum;
import com.ts.api.common.constant.productflow.ProductApplyFlowStatusEnum;
import com.ts.api.common.constant.test.ApiTestKeyConstant;
import com.ts.api.common.constant.test.ApiTestModeEnum;
import com.ts.api.common.constant.test.ApiTestResultTypeEnum;
import com.ts.api.common.localcache.DistrictCache;
import com.ts.api.exp.ApiTestValidException;
import com.ts.api.module.api.convert.core.http.client.ApiHttpMessage;
import com.ts.api.module.api.convert.plan.http.ApiPlanHttpHandler;
import com.ts.api.module.api.entity.ApiUserRequest;
import com.ts.api.module.api.entity.po.ApiKeyPO;
import com.ts.api.module.common.entity.DistrictPO;
import com.ts.api.module.product.entity.po.ProductApplyFlowPO;
import com.ts.api.module.product.entity.po.ProductPO;
import com.ts.api.module.product.entity.po.ProductPlanPO;
import com.ts.api.module.product.entity.qo.ProductApplyFlowQO;
import com.ts.api.module.product.service.ProductApplyFlowService;
import com.ts.api.module.product.service.ProductPlanService;
import com.ts.api.module.product.service.ProductPlanTypeService;
import com.ts.api.module.product.service.ProductService;
import com.ts.api.module.test.message.ApiTestMessage;
import com.ts.api.module.test.message.ApiTestResultMessage;
import com.ts.api.module.test.message.ApiTestResultMessageItem;
import com.ts.api.module.test.service.ApiTestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ApiTestServiceImpl implements ApiTestService {

    @Autowired
    private ApiPlanHttpHandler apiPlanHttpHandler;
    @Autowired
    private ProductService productService;
    @Autowired
    private ProductPlanService productPlanService;
    @Autowired
    private ProductPlanTypeService productPlanTypeService;
    @Autowired
    private ProductApplyFlowService productApplyFlowService;

    @Override
    public ApiTestMessage getMessage(RequestVO requestVO) throws ApiTestValidException {
        String body = requestVO.getBody();

        if (ValidParam.isEmpty(body)) {
            throw new ApiTestValidException("请求体为空");
        }
        String data = JsonUtils.getNode(body, "data");
        if (ValidParam.isEmpty(data)) {
            throw new ApiTestValidException("传递消息为空");
        }

        try {
            //  解密
            AES ecb = AES.createEcb(HexUtils.decode(ApiTestKeyConstant.KEY));
            String decryptData = ecb.decryptFromHexStr(data);
            ApiTestMessage apiTestMessage = JsonUtils.toBean(decryptData, ApiTestMessage.class);

            if (apiTestMessage == null) {
                throw new ApiTestValidException("解密消息实体为空");
            }
            return apiTestMessage;
        } catch (Exception e) {
            if (e instanceof ApiTestValidException validExp) {
                throw validExp;
            }
            throw new ApiTestValidException("解密失败");
        }
    }

    @Override
    public ApiTestResultMessage testOrg(ApiTestMessage apiTestMessage) {
        //  获取测试模式
        String testModeType = apiTestMessage.getTestModeType();
        //  分装apiUserInfo对象
        ApiUserRequest apiUserRequest = apiTestMessage.getApiUserRequest();

        Long productPlanId = apiTestMessage.getProductPlanId();
        Assert.isNotNullThrows(productPlanId, new ApiTestValidException("非法2"));

        //  获取计划信息
        ProductPlanPO productPlanPO = productPlanService.get(productPlanId);
        Assert.isNotNullThrows(productPlanPO, new ApiTestValidException("信息非法"));
        //  获取主体信息
        ProductPO productPO = productService.get(productPlanPO.getLoanProductId());

        //  返回消息实体
        ApiTestResultMessage resultMessage = new ApiTestResultMessage();

        //  本地机构无须测试
        if (productPlanTypeService.hasLocalOrgPlan(productPO, productPlanPO)) {
            ApiTestResultMessageItem dataExchangeResult = ApiTestResultMessageItem.ofLocalProduct();
            dataExchangeResult.setRequestBody(JsonUtils.toJson(apiTestMessage.getApiUserRequest()));
            resultMessage.setDataExchangeResult(dataExchangeResult);
            return resultMessage;
        }

        //  拷贝原始请求
        ApiUserRequest copyApiUserRequest = CopyUtils.copy(apiUserRequest, ApiUserRequest.class);

        //  发送撞库测试
        ApiKeyPO apiKeyPO = new ApiKeyPO();
        apiKeyPO.setApiClientId("12345678");
        apiKeyPO.setApiTimeoutLimit(100000);

        //  发送撞库请求
        ApiHttpMessage dataExchangeHttp = apiPlanHttpHandler.sendApiDataExchange(apiKeyPO, copyApiUserRequest, productPO, productPlanPO);
        ApiTestResultMessageItem dataExchangeResultMessage = ApiTestResultMessageItem.ofHttp(dataExchangeHttp, ApiTestResultTypeEnum.DATA_EXCHANGE);
        resultMessage.setDataExchangeResult(dataExchangeResultMessage);
        if (ValidParam.isNotEmpty(dataExchangeHttp.getErrorMsg())) {
            Log.get().info("机构撞库联调出现错误:{}", dataExchangeHttp.getStackMsg());
        }

        //  如果下游无分发则直接返回
        if (!dataExchangeHttp.hasSuc()) {
            ApiTestResultMessageItem dataExchangeResult = resultMessage.getDataExchangeResult();
            dataExchangeResult.setErrorMessage("下游无匹配记录");
            return resultMessage;
        }

        //  如果只撞库模式则直接返回
        if (ApiTestModeEnum.DATA_EXCHANGE.hasType(testModeType)) {
            return resultMessage;
        }

        //  发起进件测试
        ApiHttpMessage applyHttp = apiPlanHttpHandler.sendApply(copyApiUserRequest, productPO, productPlanPO);
        ApiTestResultMessageItem applyResultMessage = ApiTestResultMessageItem.ofHttp(applyHttp, ApiTestResultTypeEnum.APPLY);
        resultMessage.setApplyResult(applyResultMessage);
        if (ValidParam.isNotEmpty(applyHttp.getErrorMsg())) {
            Log.get().info("机构进件联调出现错误:{}", applyHttp.getStackMsg());
        }
        return resultMessage;
    }

    @Override
    public ApiTestResultMessage testPlatV2(ApiTestMessage apiTestMessage) {
        //  获取测试模式
        String testModeType = apiTestMessage.getTestModeType();
        //  分装apiUserInfo对象
        ApiUserRequest apiUserRequest = apiTestMessage.getApiUserRequest();

        Long productPlanId = apiTestMessage.getProductPlanId();
        Assert.isNotNullThrows(productPlanId, new ApiTestValidException("非法2"));

        //  获取计划信息
        ProductPlanPO productPlanPO = productPlanService.get(productPlanId);
        Assert.isNotNullThrows(productPlanPO, new ApiTestValidException("信息非法"));
        //  获取主体信息
        ProductPO productPO = productService.get(productPlanPO.getLoanProductId());

        //  返回消息实体
        ApiTestResultMessage resultMessage = new ApiTestResultMessage();

        //  拷贝原始请求
        ApiUserRequest copyApiUserRequest = CopyUtils.copy(apiUserRequest, ApiUserRequest.class);

        //  插入撞库成功流程
        ProductApplyFlowPO productApplyFlowPO = new ProductApplyFlowPO();
        productApplyFlowPO.setApiClientId("123456789");
        productApplyFlowPO.setLoanChannelId(0L);
        productApplyFlowPO.setReqId(ClassConvertUtils.toLong(copyApiUserRequest.getReqId()));
        productApplyFlowPO.setSrcType(ProductApplyFlowSrcTypeEnum.API.getType());
        productApplyFlowPO.setStatus(ProductApplyFlowStatusEnum.CHANNEL_DATA_EXCHANGE.getType());
        productApplyFlowPO.setPhoneMd5(copyApiUserRequest.getPhoneMd5());
        productApplyFlowPO.setCreateTime(DateUtils.currentTime());
        productApplyFlowPO.setLoanProductId(productPO.getId());
        productApplyFlowPO.setLoanProductPlanId(productPlanId);
        DistrictPO districtPO = DistrictCache.getByName(copyApiUserRequest.getCity());
        productApplyFlowPO.setAreaCode(districtPO.getCode());
        productApplyFlowPO.setAreaName(districtPO.getName());
        productApplyFlowPO.setBizStatus("1");

        //  发送撞库测试
        ApiKeyPO apiKeyPO = new ApiKeyPO();
        apiKeyPO.setApiClientId("12345678");
        apiKeyPO.setApiTimeoutLimit(100000);

        //  发送撞库请求
        ApiHttpMessage dataExchangeHttp = apiPlanHttpHandler.sendApiDataExchange(apiKeyPO, copyApiUserRequest, productPO, productPlanPO);
        ApiTestResultMessageItem dataExchangeResultMessage = ApiTestResultMessageItem.ofHttp(dataExchangeHttp, ApiTestResultTypeEnum.DATA_EXCHANGE);
        resultMessage.setDataExchangeResult(dataExchangeResultMessage);
        if (ValidParam.isNotEmpty(dataExchangeHttp.getErrorMsg())) {
            Log.get().info("半流程撞库联调出现错误:{}", dataExchangeHttp.getStackMsg());
        }

        //  如果下游无分发则直接返回
        if (!dataExchangeHttp.hasSuc()) {
            ApiTestResultMessageItem dataExchangeResult = resultMessage.getDataExchangeResult();
            dataExchangeResult.setErrorMessage("下游无匹配记录");
            return resultMessage;
        }

        //  如果只撞库模式则直接返回
        if (ApiTestModeEnum.DATA_EXCHANGE.hasType(testModeType)) {
            return resultMessage;
        }

        //  插入撞库成功消息
        productApplyFlowService.insert(productApplyFlowPO, false);
        return resultMessage;
    }

    @Override
    public ApiTestResultMessage testPlatV2PullApply(ApiTestMessage apiTestMessage) {
        //  分装apiUserInfo对象
        ApiUserRequest apiUserRequest = apiTestMessage.getApiUserRequest();
        ApiUserRequest copyApiUserRequest = CopyUtils.copy(apiUserRequest, ApiUserRequest.class);

        Long productPlanId = apiTestMessage.getProductPlanId();
        Assert.isNotNullThrows(productPlanId, new ApiTestValidException("非法2"));

        //  获取计划信息
        ProductPlanPO productPlanPO = productPlanService.get(productPlanId);
        Assert.isNotNullThrows(productPlanPO, new ApiTestValidException("信息非法"));
        //  获取主体信息
        ProductPO productPO = productService.get(productPlanPO.getLoanProductId());

        //  返回消息实体
        ApiTestResultMessage resultMessage = new ApiTestResultMessage();

        //  获取下游拉取进件回调成功流程数据
        ProductApplyFlowQO productApplyFlowQO = new ProductApplyFlowQO();
        productApplyFlowQO.setProductId(productPO.getId());
        productApplyFlowQO.setProductPlanId(productPlanId);
        productApplyFlowQO.setPhoneMd5(copyApiUserRequest.getPhoneMd5());
        productApplyFlowQO.setStatus(ProductApplyFlowStatusEnum.CHANNEL_PULL_APPLY_NOTICE.getType());
        ProductApplyFlowPO sucNoticeFlow = productApplyFlowService.get(productApplyFlowQO);

        if (ValidParam.isNotNull(sucNoticeFlow)) {
            ApiTestResultMessageItem pullApplyNoticeResult = ApiTestResultMessageItem.ofProductApplyFlow(sucNoticeFlow, ApiTestResultTypeEnum.APPLY);
            resultMessage.setPullApplyNoticeResult(pullApplyNoticeResult);

            //  发起进件测试
            ApiHttpMessage applyHttp = apiPlanHttpHandler.sendApply(copyApiUserRequest, productPO, productPlanPO);
            ApiTestResultMessageItem applyResultMessage = ApiTestResultMessageItem.ofHttp(applyHttp, ApiTestResultTypeEnum.APPLY);
            resultMessage.setApplyResult(applyResultMessage);
            if (ValidParam.isNotEmpty(applyHttp.getErrorMsg())) {
                Log.get().info("半流程进件联调出现错误:{}", applyHttp.getStackMsg());
            }
        }
        return resultMessage;
    }

    @Override
    public ApiTestResultMessage testPlatV3(ApiTestMessage apiTestMessage) {
        //  获取测试模式
        String testModeType = apiTestMessage.getTestModeType();
        //  分装apiUserInfo对象
        ApiUserRequest apiUserRequest = apiTestMessage.getApiUserRequest();

        Long productPlanId = apiTestMessage.getProductPlanId();
        Assert.isNotNullThrows(productPlanId, new ApiTestValidException("非法2"));

        //  获取计划信息
        ProductPlanPO productPlanPO = productPlanService.get(productPlanId);
        Assert.isNotNullThrows(productPlanPO, new ApiTestValidException("信息非法"));
        //  获取主体信息
        ProductPO productPO = productService.get(productPlanPO.getLoanProductId());

        //  返回消息实体
        ApiTestResultMessage resultMessage = new ApiTestResultMessage();

        //  拷贝原始请求
        ApiUserRequest copyApiUserRequest = CopyUtils.copy(apiUserRequest, ApiUserRequest.class);

        //  发送撞库测试
        ApiKeyPO apiKeyPO = new ApiKeyPO();
        apiKeyPO.setApiTimeoutLimit(100000);

        //  发送撞库请求
        ApiHttpMessage dataExchangeHttp = apiPlanHttpHandler.sendApiDataExchange(apiKeyPO, copyApiUserRequest, productPO, productPlanPO);
        ApiTestResultMessageItem dataExchangeResultMessage = ApiTestResultMessageItem.ofHttp(dataExchangeHttp, ApiTestResultTypeEnum.DATA_EXCHANGE);
        resultMessage.setDataExchangeResult(dataExchangeResultMessage);
        if (ValidParam.isNotEmpty(dataExchangeHttp.getErrorMsg())) {
            Log.get().info("全流程撞库联调出现错误:{}", dataExchangeHttp.getStackMsg());
        }

        //  如果下游无分发则直接返回
        if (!dataExchangeHttp.hasSuc()) {
            ApiTestResultMessageItem dataExchangeResult = resultMessage.getDataExchangeResult();
            dataExchangeResult.setErrorMessage("下游无匹配记录");
            return resultMessage;
        }

        //  如果只撞库模式则直接返回
        if (ApiTestModeEnum.DATA_EXCHANGE.hasType(testModeType)) {
            return resultMessage;
        }

        //  发起进件测试
        ApiHttpMessage applyHttp = apiPlanHttpHandler.sendApply(copyApiUserRequest, productPO, productPlanPO);
        ApiTestResultMessageItem applyResultMessage = ApiTestResultMessageItem.ofHttp(applyHttp, ApiTestResultTypeEnum.APPLY);
        resultMessage.setApplyResult(applyResultMessage);
        if (ValidParam.isNotEmpty(applyHttp.getErrorMsg())) {
            Log.get().info("全流程进件联调出现错误:{}", applyHttp.getStackMsg());
        }
        return resultMessage;
    }
}
